﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;

namespace TEAA
{
    public class BinaryFileSystemManager: FileSystemManager
    {

        /// <summary>
        /// The file extension to use for binary table files
        /// </summary>
        private const string tableFileExtension = ".bin";

        /// <summary>
        /// The file extension to use for index files
        /// </summary>
        private const string indexFileExtension = ".ind";


        /// <summary>
        /// Get table file extension
        /// </summary>
        /// <returns>Table file extension</returns>
        public override string GetTableFilesExtension()
        {
            return tableFileExtension;
        }

        /// <summary>
        /// Get index file extension
        /// </summary>
        /// <returns>Index file extension</returns>
        public override string GetIndexFilesExtension()
        {
            return indexFileExtension;
        }

        /// <summary>
        /// Create a new database
        /// </summary>
        /// <param name="databaseRootLocation">Path to database root location</param>
        /// <param name="databaseName">Name of the new database</param>
        /// <returns>Path to created database</returns>
        public override string CreateNewDatabase(string databaseRootLocation, string databaseName)
        {
            string returnPath;
            try
            {
                returnPath = FileManager.CreateNewFolder(databaseRootLocation, databaseName);
            }
            catch (Exception e)
            {
                throw new Exception("Could not create new database folder! ", e);
            }
            return returnPath;
        }

        /// <summary>
        /// Create a new table
        /// </summary>
        /// <param name="databaseRootLocation">Path to database root location</param>
        /// <param name="databaseName">Name of the database</param>
        /// <param name="tableName">Name of the new table</param>
        /// <returns>Path to created table</returns>
        public override string CreateNewTable(string databaseRootLocation, string databaseName, string tableName)
        {
            string databasePath = databaseRootLocation + Path.DirectorySeparatorChar + databaseName;
            string path = databasePath + Path.DirectorySeparatorChar + tableName;
            string tableNameFile = tableName + tableFileExtension;

            string returnPath;
            try
            {
                FileManager.CreateNewFolder(databasePath, tableName);
                returnPath = FileManager.CreateNewFile(path, tableNameFile);
            }
            catch (Exception e)
            {
                throw new Exception("Could not create new table file! ", e);
            }
            return returnPath;
        }

        /// <summary>
        /// Delete a database
        /// </summary>
        /// <param name="databaseRootLocation">Path to database root location</param>
        /// <param name="databaseName">Name of the database</param>
        /// <returns>>Database root location</returns>
        public override string DeleteDatabase(string databaseRootLocation, string databaseName)
        {
            string path = databaseRootLocation + Path.DirectorySeparatorChar + databaseName;

            string returnPath;
            try
            {
                returnPath = FileManager.DeleteFolder(path);
            }
            catch (Exception e)
            {
                throw new Exception("Could not delete database folder! ", e);
            }
            return returnPath;
        }

        /// <summary>
        /// Delete a table
        /// </summary>
        /// <param name="databaseRootLocation">Path to database root location</param>
        /// <param name="databaseName">Name of the database</param>
        /// <param name="tableName">Name of the table</param>
        /// <returns>Database path</returns>
        public override string DeleteTable(string databaseRootLocation, string databaseName, string tableName)
        {
            string path = databaseRootLocation + Path.DirectorySeparatorChar + databaseName +
                Path.DirectorySeparatorChar + tableName;

            string returnPath;
            try
            {
                returnPath = FileManager.DeleteFolder(path);
            }
            catch (Exception e)
            {
                throw new Exception("Could not delete table file! ", e);
            }
            return returnPath;
        }

        /// <summary>
        /// Rename a database
        /// </summary>
        /// <param name="databaseRootLocation">Path to database root location</param>
        /// <param name="databaseName">Name of the database</param>
        /// <param name="newDatabaseName">New name of the database</param>
        /// <returns>New database path</returns>
        public override string RenameDatabase(string databaseRootLocation, string databaseName, string newDatabaseName)
        {
            string path = databaseRootLocation + Path.DirectorySeparatorChar + databaseName;

            string returnPath;
            try
            {
                returnPath = FileManager.RenameFolder(path, newDatabaseName);
            }
            catch (Exception e)
            {
                throw new Exception("Could not rename database folder! ", e);
            }
            return returnPath;
        }

        /// <summary>
        /// Rename a table
        /// </summary>
        /// <param name="databaseRootLocation">Path to database root location</param>
        /// <param name="databaseName">Name of the database</param>
        /// <param name="tableName">Name of the table</param>
        /// <param name="newTableName">New name of the table</param>
        /// <returns>New table path</returns>
        public override string RenameTable(string databaseRootLocation, string databaseName, string tableName, string newTableName)
        {
            string tablePath = databaseRootLocation + Path.DirectorySeparatorChar + databaseName + Path.DirectorySeparatorChar + tableName;
            string newTableNameFile = newTableName + tableFileExtension;

            string returnPath;
            try
            {
                string newTablePath = FileManager.RenameFolder(tablePath, newTableName);
                string path = newTablePath + Path.DirectorySeparatorChar + tableName + tableFileExtension;
                returnPath = FileManager.RenameFile(path, newTableNameFile);
            }
            catch (Exception e)
            {
                throw new Exception("Could not rename table file! ", e);
            }
            return returnPath;
        }

        /// <summary>
        /// Create a new index
        /// </summary>
        /// <param name="databaseRootLocation">Path to database root location</param>
        /// <param name="databaseName">Name of the database</param>
        /// <param name="tableName">Name of the table</param>
        /// <param name="indexName">Name of the index</param>
        /// <returns>Path to created index</returns>
        public override string CreateNewIndex(string databaseRootLocation, string databaseName, string tableName, string indexName)
        {
            string path = databaseRootLocation + Path.DirectorySeparatorChar + databaseName + Path.DirectorySeparatorChar + tableName;
            string indexNameFile = indexName + indexFileExtension;

            string returnPath;
            try
            {
                returnPath = FileManager.CreateNewFile(path, indexNameFile);
            }
            catch (Exception e)
            {
                throw new Exception("Could not create index file! ", e);
            }
            return returnPath;
        }

        /// <summary>
        /// Delete an index
        /// </summary>
        /// <param name="databaseRootLocation">Path to database root location</param>
        /// <param name="databaseName">Name of the database</param>
        /// <param name="tableName">Name of the table</param>
        /// <param name="indexName">Name of the index</param>
        /// <returns>Table path</returns>
        public override string DeleteIndex(string databaseRootLocation, string databaseName, string tableName, string indexName)
        {
            string path = databaseRootLocation + Path.DirectorySeparatorChar + databaseName +
                Path.DirectorySeparatorChar + tableName + Path.DirectorySeparatorChar + indexName + indexFileExtension;

            string returnPath;
            try
            {
                returnPath = FileManager.DeleteFile(path);
            }
            catch (Exception e)
            {
                throw new Exception("Could not delete index file! ", e);
            }
            return returnPath;
        }

        /// <summary>
        /// Get all available databases from file system
        /// </summary>
        /// <param name="databaseRootLocation">Root location of databases</param>
        /// <returns>List of databases</returns>
        public override List<string> GetDatabases(string databaseRootLocation)
        {
            List<string> databases;
            try
            {
                databases = FileManager.GetFolders(databaseRootLocation);
            }
            catch (Exception e)
            {
                throw new Exception("Could not get databases' folders! ", e);
            }
            return databases;
        }

        /// <summary>
        /// Get all available tables from file system
        /// </summary>
        /// <param name="databaseRootLocation">Root location of databases</param>
        /// <param name="databaseName">Name of the database</param>
        /// <returns>List of databases</returns>
        public override List<string> GetTables(string databaseRootLocation, string databaseName)
        {
            List<string> tables;
            try
            {
                string path = databaseRootLocation + Path.DirectorySeparatorChar + databaseName;
                tables = FileManager.GetFolders(path);
                List<string> toRemove = new List<string>();
                foreach (string table in tables)
                {
                    string tableFilePath = path + Path.DirectorySeparatorChar + table + Path.DirectorySeparatorChar +
                        table + tableFileExtension;
                    if (!File.Exists(tableFilePath))
                        toRemove.Add(table);
                }
                foreach (string table in toRemove)
                    tables.Remove(table);
            }
            catch (Exception e)
            {
                throw new Exception("Could not get tables' folders or files! ", e);
            }
            return tables;
        }

    }
}
